package com.hulk.limitb.strategy;


import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import com.google.common.util.concurrent.RateLimiter;
import com.hulk.limitb.annotation.Limitb;
import com.hulk.limitb.enums.LimitType;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;


/**
 * Created hulk  on 2019/05/28.
 * Content :简单内存限流
 */
@Slf4j
public class SimpleLimitStrategy extends LimitStrategy {

    private static final LimitType SIMPLE = LimitType.SIMPLE;

    //创建缓存，默认4毫秒过期
    private static final  TimedCache<String, RateLimiter> LIMITEB_CACHE = CacheUtil.newTimedCache(60);


    @SneakyThrows
    @Override
    public boolean execute(String key,  Limitb limit) {
        RateLimiter rateLimiter = LIMITEB_CACHE.get(key);
        if (rateLimiter == null) {
            rateLimiter = RateLimiter.create(div(limit.maxCount(), limit.seconds(), 4));
            LIMITEB_CACHE.put(key, rateLimiter,limit.seconds()*1000);
        }
        if (!rateLimiter.tryAcquire()) {
            log.warn(SIMPLE.name() + ":限流中......");
            return false;
        }
        return true;
    }

    /**
     * 两个Double数相除，并保留scale位小数
     *
     * @param v1
     * @param v2
     * @param scale
     * @return Double
     */
    private static double div(long v1, long
            v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


}
